-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(delegation): load genesis state #26
feat(delegation): load genesis state #26
Conversation
The ValidateID function checks whether a provided ID is lowercase, has exactly one underscore with non-empty strings on each side (with the second one being a uint64), and, optionally that the string on the left side is a hex address.
Since Cosmos uses an IAVL+ based tree, the order of (unrelated) edits to the leaf nodes can impact the state root. Even though protobuf guarantees the order of a map when serializing it, it cannot guarantee that the order will be maintained once the map is deserialized into Golang. Hence, we cannot use a map during genesis (or anywhere meaningful at all).
The total delegated amount is not required at genesis and only adds an additional level of complexity that we don't need.
...for total delegated amount removal.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
// #nosec G703 // already validated | ||
stakerAddress, lzID, _ := assetstype.ParseID(stakerID) | ||
// we have checked IsHexAddress already | ||
stakerAddressBytes := common.HexToAddress(stakerAddress) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the genesis state contains a lot of delegate information, the current nested loop may affect the performance of the initialization. Consider whether it is possible to improve efficiency by optimizing data structures or parallel processing.
- Consider distributing processing operations on each delegate to different goroutines to execute in parallel. Ensure data consistency and thread safety when processing in parallel.Pay attention to the number of goroutines to avoid resource contention caused by creating too many goroutines
- If the delegateTo function supports batch processing, that is, processing multiple delegates at a time, we can collect a batch of delegates in each goroutine and call delegateTo to process them. This reduces the number of function calls and increases efficiency.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1. It is not trivial to build something like this because the order of goroutine
execution is not guaranteed. This can result in inconsistency across nodes in calculating the state root, since it depends on the order of insertion.
2. Within delegateTo
, there are 6 different function calls, only 4 of which can be batched either on the staker + asset level or on the operator + asset level. Others cannot be batched, hence, batching is not necessarily possible.
I have added a TODO for this.
// Validate performs basic genesis state validation returning an error upon any | ||
// failure. | ||
func (gs GenesisState) Validate() error { | ||
stakers := make(map[string]struct{}, len(gs.Delegations)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
During the verification process, for each level of data (stakeholder, asset, operator), a separate hash table is used to check for uniqueness. Be aware that memory usage may increase when processing large amounts of data.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed, added a TODO for this.
- parallelization of loading genesis - size of hash map for validation. I don't believe this is a super big concern given Cosmos genesis has a similar validation and the size of their genesis files is also very big.
This PR subsumes #27 within itself, and therefore should be merged after that one. For ease of review, this PR may be reviewed after the merge of #27 happens and this PR is rebased.
The
x/delegation
module needs to load the genesis state of delegations (for each possible combination of staker, asset and operator) for the network to successfully bootstrap with the rPOS process.The genesis state is structured as follows.
At genesis, the module should perform these delegations as it would if the chain were live. To do this, we call the exact same
DelegateTo
function that is called by the precompile and use a flag to skip (1) the operator frozen check, (2) the operator module update and (3) the delegation hooks.The stateless validation uses this algorithm:
stakerID
is valid: lowercase, exactly one underscore, with the left side of the underscore non-empty and a hex address, and the right side a hexuint64
.stakerID
, there is no repeatingassetID
.assetID
is valid (defined above).LayerZeroID
derived from thestakerID
equals that derived from theassetID
for each providedstakerID
+assetID
combination.